const throttle = function throttle(func, wait, options) {
  let context
  let args
  let result = void 0
  let timeout
  let previous = 0
  if (!options) options = {}
  const later = function later() {
    previous = options.leading === false ? 0 : Date.now()
    timeout = null
    result = func.apply(context, args)
    if (!timeout) context = args = null
  }
  return function () {
    const now = Date.now()
    if (!previous && options.leading === false) previous = now
    const remaining = wait - (now - previous)
    context = this
    args = arguments
    if (remaining <= 0 || remaining > wait) {
      clearTimeout(timeout)
      timeout = null
      previous = now
      result = func.apply(context, args)
      if (!timeout) context = args = null
    } else if (!timeout && options.trailing !== false) {
      timeout = setTimeout(later, remaining)
    }
    return result
  }
}
Component({
  options: {
    styleIsolation: 'apply-shared',
    virtualHost: true, // 不受组件上样式影响
    pureDataPattern: /^_/ //纯数据字段，只做组件内数据的处理，不会呈现在页面上，也不会向子组件传递
  },
  properties: {
    list: {
      type: Array,
      value: [],
      observer(newVal) {
        console.log('observer list')
        if (newVal.length === 0) return
        const alphabet = this.data.list.map((item, index) => {
          this.data._tops[index] = 2e10 // 2* 10的10次方
          return item.alpha
        })
        this._sharedTops.value = this.data._tops
        this.setData(
          {
            alphabet,
            current: alphabet[0]
          },
          () => {
            this.computedSize()
          }
        )
      }
    }
  },
  data: {
    current: 'A',
    intoView: '',
    touching: false,
    alphabet: [],
    _vibrated: true,
    _tops: [],
    _anchorItemH: 0,
    _anchorItemW: 0,
    _anchorTop: 0
  },
  observers: {
    current: function (current) {
      this._sharedCurrentIdx.value = this.data.alphabet.indexOf(current)
    }
  },
  lifetimes: {
    created() {
      console.log('created')
      this._handlePan = throttle(this._handlePan, 100, {})
      this._sharedTops = wx.worklet.shared([])
      this._sharedScrollTop = wx.worklet.shared(0)
      this._sharedHeight = wx.worklet.shared(0)
      this._sharedCurrentIdx = wx.worklet.shared(0)
    },
    attached() {
      console.log('attached')
      // scroll-view高度
      this.createSelectorQuery()
        .select('.scroll-view')
        .boundingClientRect((ress) => {
          this._sharedHeight.value = res.height
        })
        .exec()

      // 右侧目录计算
      const query = this.createSelectorQuery()
      query
        .select('.anchor-list')
        .boundingClientRect((rect) => {
          this.data._anchorItemH = rect.height / this.data.alphabet.length
          this.data._anchorItemW = rect.width
          this.data._anchorTop = rect.top
        })
        .exec()
    }
  },
  methods: {
    computedSize() {
      // 在skyline中如果使用list-view、grid-view会按需渲染特性，取其子节点的clientRect
      // 时若不在屏幕中是取不到的
      this.data.alphabet.forEach((element, index) => {
        this.createSelectorQuery()
          .select(`#${element}`)
          .boundingClientRect((res) => {
            this.data._tops[index] = res.top
            this._sharedTops.value = this.data._tops
          })
          .exec()
      })
    },
    handlePan(e) {
      this._handlePan(e)
    },
    _handlePan(e) {
      console.log('_handlePan')
      const data = this.data
      const clientY = e.changedTouches[0].clientY
      const index = Math.floor((clientY - data._anchorTop) / data._anchorItemH)
      const current = data.alphabet[index]

      if (current !== this.data.current) {
        wx.vibrateShort({
          type: 'heavy'
        })
        this.setData({
          current,
          intoView: current,
          touching: true
        })
      }
    },
    cancelPan() {
      setTimeout(() => {
        this.setData({
          touching: false
        })
      }, 150)
    },
    handleScroll(e) {
      'worklet'
      // console.log(e)
      const scrollTop = e.detail.scrollTop
      console.log(scrollTop)
      // 用于计算每一个header的offsetTop
      this._sharedScrollTop.value = scrollTop
      // 下面判断当前选中状态，按需更新
      const tops = this._sharedTops.value
      for (let i = tops.length - 1; i >= 0; i--) {
        // header超过屏幕的一半就改为选中状态
        if (scrollTop + this._sharedHeight.value / 2 > tops[i]) {
          if (i !== this._sharedCurrentIdx.value) {
            // worklet 函数运行在ui线程，setData调用要抛回JS线程执行
            wx.worklet.runOnJS(this.updateCurrent.bind(this))(i)
          }
          break
        }
      }
    },
    updateCurrent(idx) {
      if (this.data.touching) return
      this.setData({ current: this.data.alphabet[idx] })
    }
  }
})
